Categories
TypeScript Best Practices

TypeScript Best Practices — String Search, Union Styles, and More

Spread the love

TypeScript is an easy to learn extension of JavaScript. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust TypeScript code.

In this article, we’ll look at the best practices to following when writing code with TypeScript, including better ways to check the start and end of strings.

Also, we look why we should check all the types of a union type and make sure that both operands are of the same type before using the + operator.

Use startsWith and endsWith Instead of Other Equivalent Methods to Check Substrings

If we’re checking whether a string starts with or ends with some substring, then we should use the startsWith or endsWith methods to search for substrings.

For instance, instead of using:

foo.indexOf('bar') === 0;

or:

foo.substring(0, 3) === 'bar';

We can write:

foo.startsWith('bar');

Likewise, if we want if a string ends with something, instead of writing:

foo.slice(-3) === 'bar';

or:

foo.substring(foo.length - 3) === 'bar';

We can write:

foo.endsWith('bar');

It saves us lots of headaches with dealing with string indexes.

Use //@ts-expect-error over //@ts-ignore

//@ts-ignore suppresses all TypeScript errors before the erroring line.

If we use //@ts-expect-error , which is available since TypeScript 3.9, we can tell people that the error they encounter is expected instead of suppressing all errors.

Use any Function or a Method that Returns a Promise to be Marked async

The async-await syntax is a shorter way to write a function that returns a promise.

Therefore, we should use it as much as possible.

For instance, instead of writing:

const foo = () => Promise.resolve('foo');

We write:

const foo = async () => Promise.resolve('value');

Require array.sort Calls to Always Provide a Compare Function

By default, the sort method that’s part of an array instance sorts everything as if they’re strings.

Therefore, we should provide a comparator function so that we can compare our array entries properly.

For instance, if we want to sort numbers in ascending order, instead of writing:

const arr = [2, 3, 1];
arr.sort();

We write:

const arr = [2, 3, 1];
arr.sort((a, b) => a - b);

When Adding 2 Variables, Operands Must Both be of Type Number or String

The + operator is both used for addition or concatenation.

Therefore, we should make sure that we’re doing what we want by making both operands the same type.

Otherwise, we may get unexpected results.

For instance, instead of writing:

const foo = 1 + '1';

which will concatenate the operands, we should write:

const foo = 1 + Number('1');

so that they’re both numbers and we can add them together.

Use Template Expressions for Strings

Template strings are much better than regular strings. We can put expressions in them and we can make multiline expressions without hassle.

So we should use them as much as possible.

Therefore, instead of writing:

const arg = 'foo ' + bar;

We should write:

const arg = `foo ${bar}`;

Restrict Types Allowed in Boolean Expressions

We may want to restrict the types allowed in boolean expressions.

This may be useful if we don’t want automatic casting of truthy and falsy values.

For instance, instead of writing:

let foo = bar || 'baz';

We may write:

let foo = typeof bar !== 'undefined' ? bar : 'baz';

Make Sure that Union Type Checks are Exhaustive

We want to make sure that union type checks are exhaustive.

This way, we make sure that we don’t miss any cases in union types.

For instance, instead of writing:

type Color = "red" | "green" | "blue";

const color = "red" as Color;
let result = 0;

switch (color) {
  case "red": {
    result = 1;
    break;
  }
}

We write:

type Color = "red" | "green" | "blue";

const color = "red" as Color;
let result = 0;

switch (color) {
  case "red": {
    result = 1;
    break;
  }
  case "green": {
    result = 2;
    break;
  }
  case "blue": {
    result = 3;
    break;
  }
}

or:

type Color = "red" | "green" | "blue";

const color = "red" as Color;
let result = 0;

switch (color) {
  case "red": {
    result = 1;
    break;
  }
  default: {
    result = 100;
    break;
  }
}

Now we took all cases into account.

Conclusion

We should use startsWith and endsWith to check if a string starts with or ends with something.

Also, we may want to restrict the types allowed in boolean expressions to avoid casting.

And we want to make sure that we check all the types in a union type.

Finally, if we use the + operator, we should make sure that both operands are of the same type to prevent unexpected results.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *